/***************************************************
File:           LPK_ModifySpriteOnEvent.cs
Authors:        Christopher Onorati
Last Updated:   7/10/2019
Last Version:   2018.3.14

Description:
  This component can be added to any object to cause
  it to modify an object's Sprite properties upon
  receiving an event.

This script is a basic and generic implementation of its 
functionality. It is designed for educational purposes and 
aimed at helping beginners.

Copyright 2018-2019, DigiPen Institute of Technology
***************************************************/

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI; /* Image */
using UnityEditor;

namespace LPK
{

/**
* CLASS NAME  : LPK_ModifySpriteOnEvent
* DESCRIPTION : Component used to modify the values of a sprite.
**/
public class LPK_ModifySpriteOnEvent : LPK_Component
{
    /************************************************************************************/

    public enum LPK_NonNumericModifyMode
    {
        NONE,
        SET,
        COPY,
    };

    /************************************************************************************/

    [Tooltip("Tagged object(s) whose sprite properties will be modified. Set to owner by default if both this and the tag object array are left empty.")]
    public GameObject[] m_TargetModifyObjects;

    [Tooltip("Tagged object(s) whose sprite properties will be modified. Set to owner by default if both this and the game object array are left empty.")]
    [TagDropdown]
    public string[] m_TargetTags;

    public bool m_bModifyOnSpawn;

    [System.Serializable]
    public class VisibleProperties
    {
        [Tooltip("How to modify visibility upon receiving the event.")]
        [Rename("Visible Mode")]
        public LPK_NonNumericModifyMode m_eVisibleModifyMode;

        [Tooltip("New value to set visible flag to be.")]
        [Rename("Visible")]
        public bool m_bVisible;

        [Tooltip("Object whose visible flag will be copied to the recipient's property value. Only used if mode is set to copy. Default to self if this and the tag field are left unset.")]
        [Rename("Visible Copy Target")]
        public GameObject m_pVisibleCopyTarget;

        [Tooltip("Object whose property value will be copied to the recipient's property value. Only used if mode is set to copy. Note this will only affect the first object with the tag found.")]
        [Rename("Visible Copy Tag")]
        public string m_sVisibleCopyTag;
    }

    public VisibleProperties m_VisibleProperties;

    [System.Serializable]
    public class ColorProperties
    {
        [Tooltip("How to modify color upon receiving the event.")]
        [Rename("Color Mode")]
        public LPK_NonNumericModifyMode m_eVertexColorModifyMode;

        [Tooltip("New value to set color to be.")]
        [Rename("Color Value")]
        public Color m_vecColorValue;

        [Tooltip("Object whose color will be copied to the recipient's property value. Only used if mode is set to copy. Default to self if this and the tag field are left unset.")]
        [Rename("Color Copy Target")]
        public GameObject m_pVertexColorCopyTarget;

        [Tooltip("Object whose property value will be copied to the recipient's property value. Only used if mode is set to copy. Note this will only affect the first object with the tag found.")]
        [Rename("Color Copy Tag")]
        public string m_sColorCopyTag;
    }

    public ColorProperties m_VertexColorProperties;

    [System.Serializable]
    public class TextureProperties
    {
        [Tooltip("How to modify texture upon receiving the event.")]
        [Rename("Texture Mode")]
        public LPK_NonNumericModifyMode m_eTextureModifyMode;

        [Tooltip("New value to set visible flag to be.")]
        [Rename("New Texture")]
        public Sprite m_TextureValue;

        [Tooltip("Object whose texture will be copied to the recipient's property value. Only used if mode is set to copy. Default to self if this and the tag field are left unset.")]
        [Rename("Texture Copy Target")]
        public GameObject m_pTextureCopyTarget;

        [Tooltip("Object whose property value will be copied to the recipient's property value. Only used if mode is set to copy. Note this will only affect the first object with the tag found.")]
        [Rename("Texture Copy Tag")]
        public string m_sTextureCopyTag;
    }

    public TextureProperties m_TextureProperties;

    [System.Serializable]
    public class MaterialProperties
    {
        [Tooltip("How to modify material upon receiving the event.")]
        [Rename("Material Mode")]
        public LPK_NonNumericModifyMode m_eMaterialModifyMode;

        [Tooltip("New value to set visible flag to be.")]
        [Rename("New Material")]
        public Material m_MaterialValue;

        [Tooltip("Object whose material will be copied to the recipient's property value. Only used if mode is set to copy. Default to self if this and the tag field are left unset.")]
        [Rename("Material Copy Target")]
        public GameObject m_pMaterialCopyTarget;

        [Tooltip("Object whose property value will be copied to the recipient's property value. Only used if mode is set to copy. Note this will only affect the first object with the tag found.")]
        [Rename("Material Copy Tag")]
        public string m_sMaterialCopyTag;
    }

    public MaterialProperties m_MaterialProperties;

    [Header("Event Receiving Info")]

    [Tooltip("Which event will trigger this component's action")]
    public LPK_EventObject m_EventTrigger;

    /**
    * FUNCTION NAME: Start
    * DESCRIPTION  : Sets up what event to listen to for sprite and color modification.
    * INPUTS       : None
    * OUTPUTS      : None
    **/
    override protected void OnStart()
    {
        if(m_EventTrigger)
            m_EventTrigger.Register(this);

        if (m_TargetModifyObjects.Length == 0 && m_TargetTags.Length == 0)
            m_TargetModifyObjects = new GameObject[] { gameObject };

        if(m_bModifyOnSpawn)
            SearchForModifyObjects();
    }

    /**
    * FUNCTION NAME: OnEvent
    * DESCRIPTION  : Event validation.
    * INPUTS       : _activator - Game object that activated the event.  Null is all objects.
    * OUTPUTS      : None
    **/
    override public void OnEvent(GameObject _activator)
    {
        if(!ShouldRespondToEvent(_activator))
            return;

        if (m_bPrintDebug)
            LPK_PrintDebug(this, "Event Received");

        SearchForModifyObjects();
    }

    /**
    * FUNCTION NAME: SearchForModifyObjects
    * DESCRIPTION  : Perform search for game objects to be modified.
    * INPUTS       : None
    * OUTPUTS      : None
    **/
    void SearchForModifyObjects()
    {
        SetCopyTargets();

        for (int i = 0; i < m_TargetModifyObjects.Length; i++)
        {
            if (m_TargetModifyObjects[i].GetComponent<SpriteRenderer>() != null)
                ModifySprite(m_TargetModifyObjects[i]);
            else if (m_TargetModifyObjects[i].GetComponent<Image>() != null)
                ModifyImage(m_TargetModifyObjects[i]);
        }

        for (int i = 0; i < m_TargetTags.Length; i++)
        {
            List<GameObject> taggedObjects = LPK_MultiTagManager.FindGameObjectsWithTag(gameObject, m_TargetTags[i]);

            for (int j = 0; j < taggedObjects.Count; j++)
            {
                if (taggedObjects[j].GetComponent<SpriteRenderer>() != null)
                    ModifySprite(taggedObjects[j]);
                else if (taggedObjects[j].GetComponent<Image>() != null)
                    ModifyImage(taggedObjects[j]);
            }
        }
    }

    /**
    * FUNCTION NAME: SetCopyTargets
    * DESCRIPTION  : Sets targets to copy.
    * INPUTS       : None
    * OUTPUTS      : None
    **/
    void SetCopyTargets()
    {
        if (m_VisibleProperties.m_pVisibleCopyTarget == null)
        {
            if (!string.IsNullOrEmpty(m_VisibleProperties.m_sVisibleCopyTag))
                m_VisibleProperties.m_pVisibleCopyTarget = LPK_MultiTagManager.FindGameObjectWithTag(gameObject, m_VisibleProperties.m_sVisibleCopyTag);
            else if (m_VisibleProperties.m_pVisibleCopyTarget == null)
                m_VisibleProperties.m_pVisibleCopyTarget = gameObject;
        }

        if (m_VertexColorProperties.m_pVertexColorCopyTarget == null)
        {
            if (!string.IsNullOrEmpty(m_VertexColorProperties.m_sColorCopyTag))
                m_VertexColorProperties.m_pVertexColorCopyTarget = LPK_MultiTagManager.FindGameObjectWithTag(gameObject, m_VertexColorProperties.m_sColorCopyTag);
            else if (m_VertexColorProperties.m_sColorCopyTag == null)
                m_VertexColorProperties.m_pVertexColorCopyTarget = gameObject;
        }

        if (m_TextureProperties.m_pTextureCopyTarget == null)
        {
            if (!string.IsNullOrEmpty(m_TextureProperties.m_sTextureCopyTag))
                m_TextureProperties.m_pTextureCopyTarget = LPK_MultiTagManager.FindGameObjectWithTag(gameObject, m_TextureProperties.m_sTextureCopyTag);
            else if (m_TextureProperties.m_pTextureCopyTarget == null)
                m_TextureProperties.m_pTextureCopyTarget = gameObject;
        }

        if (m_MaterialProperties.m_pMaterialCopyTarget == null)
        {
            if (!string.IsNullOrEmpty(m_MaterialProperties.m_sMaterialCopyTag))
                m_MaterialProperties.m_pMaterialCopyTarget = LPK_MultiTagManager.FindGameObjectWithTag(gameObject, m_MaterialProperties.m_sMaterialCopyTag);
            else if (m_MaterialProperties.m_pMaterialCopyTarget == null)
                m_MaterialProperties.m_pMaterialCopyTarget = gameObject;
        }
    }

    /**
    * FUNCTION NAME: ModifySprite
    * DESCRIPTION  : Modify the display of a sprite.
    * INPUTS       : modifyObject - Object to modify.
    * OUTPUTS      : None
    **/
    void ModifySprite(GameObject modifyObject)
    {
        SpriteRenderer modSprite = modifyObject.GetComponent<SpriteRenderer>();

        //Modify the visible flag property based on the mode selected
        if (m_VisibleProperties.m_eVisibleModifyMode == LPK_NonNumericModifyMode.SET)
            modSprite.enabled = m_VisibleProperties.m_bVisible;
        else if (m_VisibleProperties.m_eVisibleModifyMode == LPK_NonNumericModifyMode.COPY)
        {
            if (m_VisibleProperties.m_pVisibleCopyTarget != null && m_VisibleProperties.m_pVisibleCopyTarget.GetComponent<SpriteRenderer>() != null)
                modSprite.enabled = m_VisibleProperties.m_pVisibleCopyTarget.GetComponent<SpriteRenderer>().enabled;
        }

        //Modify the Color property based on the mode selected
        if (m_VertexColorProperties.m_eVertexColorModifyMode == LPK_NonNumericModifyMode.SET)
            modSprite.color = m_VertexColorProperties.m_vecColorValue;
        else if (m_VertexColorProperties.m_eVertexColorModifyMode == LPK_NonNumericModifyMode.COPY)
        {
            if (m_VertexColorProperties.m_pVertexColorCopyTarget != null && m_VertexColorProperties.m_pVertexColorCopyTarget.GetComponent<SpriteRenderer>() != null)
                modSprite.color = m_VertexColorProperties.m_pVertexColorCopyTarget.GetComponent<SpriteRenderer>().color;
        }

        //Modify the texture property based on the mode selected
        if (m_TextureProperties.m_eTextureModifyMode == LPK_NonNumericModifyMode.SET)
            modSprite.sprite = m_TextureProperties.m_TextureValue;
        else if (m_TextureProperties.m_eTextureModifyMode == LPK_NonNumericModifyMode.COPY)
        {
            if (m_TextureProperties.m_pTextureCopyTarget != null && m_TextureProperties.m_pTextureCopyTarget.GetComponent<SpriteRenderer>() != null)
                modSprite.sprite = m_TextureProperties.m_pTextureCopyTarget.GetComponent<SpriteRenderer>().sprite;
        }

        //Modify the material property based on the mode selected
        if (m_MaterialProperties.m_eMaterialModifyMode == LPK_NonNumericModifyMode.SET)
            modSprite.material = m_MaterialProperties.m_MaterialValue;
        else if (m_MaterialProperties.m_eMaterialModifyMode == LPK_NonNumericModifyMode.COPY)
        {
            if (m_MaterialProperties.m_pMaterialCopyTarget != null && m_MaterialProperties.m_pMaterialCopyTarget.GetComponent<SpriteRenderer>() != null)
                modSprite.material = m_MaterialProperties.m_pMaterialCopyTarget.GetComponent<SpriteRenderer>().material;
        }
    }

    /**
    * FUNCTION NAME: ModifyImage
    * DESCRIPTION  : Modify the display of a UI image.
    * INPUTS       : modifyObject - Object to modify
    * OUTPUTS      : None
    **/
    void ModifyImage(GameObject modifyObject)
    {
        Image modSprite = modifyObject.GetComponent<Image>();

        //Modify the visible flag property based on the mode selected
        if (m_VisibleProperties.m_eVisibleModifyMode == LPK_NonNumericModifyMode.SET)
            modSprite.enabled = m_VisibleProperties.m_bVisible;
        else if (m_VisibleProperties.m_eVisibleModifyMode == LPK_NonNumericModifyMode.COPY)
        {
            if (m_VisibleProperties.m_pVisibleCopyTarget != null && m_VisibleProperties.m_pVisibleCopyTarget.GetComponent<Image>() != null)
                modSprite.enabled = m_VisibleProperties.m_pVisibleCopyTarget.GetComponent<Image>().enabled;
        }

        //Modify the Color property based on the mode selected
        if (m_VertexColorProperties.m_eVertexColorModifyMode == LPK_NonNumericModifyMode.SET)
            modSprite.color = m_VertexColorProperties.m_vecColorValue;
        else if (m_VertexColorProperties.m_eVertexColorModifyMode == LPK_NonNumericModifyMode.COPY)
        {
            if (m_VertexColorProperties.m_pVertexColorCopyTarget != null && m_VertexColorProperties.m_pVertexColorCopyTarget.GetComponent<Image>() != null)
                modSprite.color = m_VertexColorProperties.m_pVertexColorCopyTarget.GetComponent<Image>().color;
        }

        //Modify the texture property based on the mode selected
        if (m_TextureProperties.m_eTextureModifyMode == LPK_NonNumericModifyMode.SET)
            modSprite.sprite = m_TextureProperties.m_TextureValue;
        else if (m_TextureProperties.m_eTextureModifyMode == LPK_NonNumericModifyMode.COPY)
        {
            if (m_TextureProperties.m_pTextureCopyTarget != null && m_TextureProperties.m_pTextureCopyTarget.GetComponent<Image>() != null)
                modSprite.sprite = m_TextureProperties.m_pTextureCopyTarget.GetComponent<Image>().sprite;
        }
    }

    /**
    * FUNCTION NAME: OnDestroy
    * DESCRIPTION  : Removes game object from the event queue.
    * INPUTS       : None
    * OUTPUTS      : None
    **/
    void OnDestroy()
    {
        if(m_EventTrigger != null)
            m_EventTrigger.Unregister(this);
    }
}

#if UNITY_EDITOR

[CustomEditor(typeof(LPK_ModifySpriteOnEvent))]
public class LPK_ModifySpriteOnEventEditor : Editor
{
    SerializedProperty targetModifyObject;
    SerializedProperty targetTags;
    SerializedProperty visibleProperties;
    SerializedProperty vertexColorProperties;
    SerializedProperty textureProperties;
    SerializedProperty materialProperties;

    SerializedProperty eventTriggers;

    /**
    * FUNCTION NAME: OnEnable
    * DESCRIPTION  : Save out serialized classes.
    * INPUTS       : None
    * OUTPUTS      : None
    **/
    void OnEnable()
    {
        targetModifyObject = serializedObject.FindProperty("m_TargetModifyObjects");
        targetTags = serializedObject.FindProperty("m_TargetTags");
        visibleProperties = serializedObject.FindProperty("m_VisibleProperties");
        vertexColorProperties = serializedObject.FindProperty("m_VertexColorProperties");
        textureProperties = serializedObject.FindProperty("m_TextureProperties");
        materialProperties = serializedObject.FindProperty("m_MaterialProperties");
  
        eventTriggers = serializedObject.FindProperty("m_EventTrigger");
    }

    /**
    * FUNCTION NAME: OnInspectorGUI
    * DESCRIPTION  : Override GUI for inspector.
    * INPUTS       : None
    * OUTPUTS      : None
    **/
    public override void OnInspectorGUI()
    {
        LPK_ModifySpriteOnEvent owner = (LPK_ModifySpriteOnEvent)target;

        LPK_ModifySpriteOnEvent editorOwner = owner.GetComponent<LPK_ModifySpriteOnEvent>();

        EditorGUI.BeginDisabledGroup(true);
        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.PrefixLabel("Script");
        editorOwner = (LPK_ModifySpriteOnEvent)EditorGUILayout.ObjectField(editorOwner, typeof(LPK_ModifySpriteOnEvent), false);
        GUILayout.EndHorizontal();
        EditorGUI.EndDisabledGroup();

        //Undo saving.
        Undo.RecordObject(owner, "Property changes on LPK_ModifySpriteOnEvent");

        //Component properties.
        GUILayout.Space(10);
        EditorGUILayout.LabelField("Component Properties", EditorStyles.boldLabel);

        EditorGUILayout.PropertyField(targetModifyObject, true);
        EditorGUILayout.PropertyField(targetTags, true);
        owner.m_bModifyOnSpawn = EditorGUILayout.Toggle(new GUIContent("Modify On Spawn", "Set to cause this component to set its modification on an object's spawn.  This component will still react to set events."), owner.m_bModifyOnSpawn);

        GUILayout.Space(10);
        EditorGUILayout.LabelField("Modifications", EditorStyles.miniBoldLabel);

        EditorGUILayout.PropertyField(visibleProperties, true);
        EditorGUILayout.PropertyField(vertexColorProperties, true);
        EditorGUILayout.PropertyField(textureProperties, true);
        EditorGUILayout.PropertyField(materialProperties, true);

        //Events
        EditorGUILayout.PropertyField(eventTriggers, true);

        //Debug properties.
        GUILayout.Space(10);
        EditorGUILayout.LabelField("Debug Properties", EditorStyles.boldLabel);

        owner.m_bPrintDebug = EditorGUILayout.Toggle(new GUIContent("Print Debug Info", "Toggle console debug messages."), owner.m_bPrintDebug);
        owner.m_sLabel = EditorGUILayout.TextField(new GUIContent("Label", "Notes for the user about this component.  This does nothing to the game or build."), owner.m_sLabel);

        //Apply changes.
        serializedObject.ApplyModifiedProperties();
    }
}

[CustomPropertyDrawer(typeof(LPK_ModifySpriteOnEvent.VisibleProperties))]
public class LPK_ModifySpriteOnEvent_VisiblePropertiesDrawer : PropertyDrawer
{
    /**
    * FUNCTION NAME: OnGUI
    * DESCRIPTION  : Override GUI for inspector.
    * INPUTS       : position - Position of the property drawer.
    *                property - Property to draw.
    *                label    - Display info.
    * OUTPUTS      : None
    **/
    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        SerializedProperty m_eVisibleModifyMode = property.FindPropertyRelative("m_eVisibleModifyMode");
        SerializedProperty m_bVisible = property.FindPropertyRelative("m_bVisible");
        SerializedProperty m_pVisibleCopyTarget = property.FindPropertyRelative("m_pVisibleCopyTarget");
        SerializedProperty m_sVisibleCopyTag = property.FindPropertyRelative("m_sVisibleCopyTag");

        int indent = EditorGUI.indentLevel;
        EditorGUI.indentLevel = 0;

        m_eVisibleModifyMode.isExpanded = EditorGUI.Foldout(new Rect(position.x, position.y, position.width, EditorGUIUtility.singleLineHeight),
                                                    m_eVisibleModifyMode.isExpanded, new GUIContent("Visible Properties"), true);

        if(m_eVisibleModifyMode.isExpanded)
        {
            EditorGUI.indentLevel++;

            EditorGUI.PropertyField(new Rect(position.x, position.y + EditorGUIUtility.singleLineHeight, position.width, EditorGUIUtility.singleLineHeight),m_eVisibleModifyMode);

            if(m_eVisibleModifyMode.enumValueIndex == (int)LPK_ModifySpriteOnEvent.LPK_NonNumericModifyMode.SET)
                EditorGUI.PropertyField(new Rect(position.x, position.y + EditorGUIUtility.singleLineHeight * 2, position.width, EditorGUIUtility.singleLineHeight),m_bVisible);

            if(m_eVisibleModifyMode.enumValueIndex == (int)LPK_ModifySpriteOnEvent.LPK_NonNumericModifyMode.COPY)
            {
                EditorGUI.PropertyField(new Rect(position.x, position.y + EditorGUIUtility.singleLineHeight * 2, position.width, EditorGUIUtility.singleLineHeight),m_pVisibleCopyTarget);
                EditorGUI.PropertyField(new Rect(position.x, position.y + EditorGUIUtility.singleLineHeight * 3, position.width, EditorGUIUtility.singleLineHeight), m_sVisibleCopyTag);
            }
        }

        EditorGUI.indentLevel = indent;

        property.serializedObject.ApplyModifiedProperties();
    }

    /**
    * FUNCTION NAME: GetPropertyHeight
    * DESCRIPTION  : Set height for this property in the inspector.
    * INPUTS       : property - Property to draw.
    *                label    - Display info.
    * OUTPUTS      : None
    **/
    public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
    {
        SerializedProperty m_eVisibleModifyMode = property.FindPropertyRelative("m_eVisibleModifyMode");

        if(m_eVisibleModifyMode.enumValueIndex == (int)LPK_ModifySpriteOnEvent.LPK_NonNumericModifyMode.SET)
            return m_eVisibleModifyMode.isExpanded ? EditorGUIUtility.singleLineHeight * 3 : EditorGUIUtility.singleLineHeight;
        else if (m_eVisibleModifyMode.enumValueIndex == (int)LPK_ModifySpriteOnEvent.LPK_NonNumericModifyMode.COPY)
            return m_eVisibleModifyMode.isExpanded ? EditorGUIUtility.singleLineHeight * 4 : EditorGUIUtility.singleLineHeight;
        else
            return m_eVisibleModifyMode.isExpanded ? EditorGUIUtility.singleLineHeight * 2 : EditorGUIUtility.singleLineHeight;
    }
}

[CustomPropertyDrawer(typeof(LPK_ModifySpriteOnEvent.ColorProperties))]
public class LPK_ModifySpriteOnEvent_ColorPropertiesDrawer : PropertyDrawer
{
    /**
    * FUNCTION NAME: OnGUI
    * DESCRIPTION  : Override GUI for inspector.
    * INPUTS       : position - Position of the property drawer.
    *                property - Property to draw.
    *                label    - Display info.
    * OUTPUTS      : None
    **/
    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        SerializedProperty m_eVertexColorModifyMode = property.FindPropertyRelative("m_eVertexColorModifyMode");
        SerializedProperty m_vecColorValue = property.FindPropertyRelative("m_vecColorValue");
        SerializedProperty m_pVertexColorCopyTarget = property.FindPropertyRelative("m_pVertexColorCopyTarget");
        SerializedProperty m_sColorCopyTag = property.FindPropertyRelative("m_sColorCopyTag");

        int indent = EditorGUI.indentLevel;
        EditorGUI.indentLevel = 0;

        m_eVertexColorModifyMode.isExpanded = EditorGUI.Foldout(new Rect(position.x, position.y, position.width, EditorGUIUtility.singleLineHeight),
                                                    m_eVertexColorModifyMode.isExpanded, new GUIContent("Color Properties"), true);

        if(m_eVertexColorModifyMode.isExpanded)
        {
            EditorGUI.indentLevel++;

            EditorGUI.PropertyField(new Rect(position.x, position.y + EditorGUIUtility.singleLineHeight, position.width, EditorGUIUtility.singleLineHeight), m_eVertexColorModifyMode);

            if(m_eVertexColorModifyMode.enumValueIndex == (int)LPK_ModifySpriteOnEvent.LPK_NonNumericModifyMode.SET)
                EditorGUI.PropertyField(new Rect(position.x, position.y + EditorGUIUtility.singleLineHeight * 2, position.width, EditorGUIUtility.singleLineHeight), m_vecColorValue);

            if(m_eVertexColorModifyMode.enumValueIndex == (int)LPK_ModifySpriteOnEvent.LPK_NonNumericModifyMode.COPY)
            {
                EditorGUI.PropertyField(new Rect(position.x, position.y + EditorGUIUtility.singleLineHeight * 2, position.width, EditorGUIUtility.singleLineHeight), m_pVertexColorCopyTarget);
                EditorGUI.PropertyField(new Rect(position.x, position.y + EditorGUIUtility.singleLineHeight * 3, position.width, EditorGUIUtility.singleLineHeight), m_sColorCopyTag);
            }
        }

        EditorGUI.indentLevel = indent;

        property.serializedObject.ApplyModifiedProperties();
    }

    /**
    * FUNCTION NAME: GetPropertyHeight
    * DESCRIPTION  : Set height for this property in the inspector.
    * INPUTS       : property - Property to draw.
    *                label    - Display info.
    * OUTPUTS      : None
    **/
    public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
    {
        SerializedProperty m_eVertexColorModifyMode = property.FindPropertyRelative("m_eVertexColorModifyMode");

        if(m_eVertexColorModifyMode.enumValueIndex == (int)LPK_ModifySpriteOnEvent.LPK_NonNumericModifyMode.SET)
            return m_eVertexColorModifyMode.isExpanded ? EditorGUIUtility.singleLineHeight * 3 : EditorGUIUtility.singleLineHeight;
        else if (m_eVertexColorModifyMode.enumValueIndex == (int)LPK_ModifySpriteOnEvent.LPK_NonNumericModifyMode.COPY)
            return m_eVertexColorModifyMode.isExpanded ? EditorGUIUtility.singleLineHeight * 4 : EditorGUIUtility.singleLineHeight;
        else
            return m_eVertexColorModifyMode.isExpanded ? EditorGUIUtility.singleLineHeight * 2 : EditorGUIUtility.singleLineHeight;
    }
}

[CustomPropertyDrawer(typeof(LPK_ModifySpriteOnEvent.TextureProperties))]
public class LPK_ModifySpriteOnEvent_TexturePropertiesDrawer : PropertyDrawer
{
    /**
    * FUNCTION NAME: OnGUI
    * DESCRIPTION  : Override GUI for inspector.
    * INPUTS       : position - Position of the property drawer.
    *                property - Property to draw.
    *                label    - Display info.
    * OUTPUTS      : None
    **/
    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        SerializedProperty m_eTextureModifyMode = property.FindPropertyRelative("m_eTextureModifyMode");
        SerializedProperty m_TextureValue = property.FindPropertyRelative("m_TextureValue");
        SerializedProperty m_pTextureCopyTarget = property.FindPropertyRelative("m_pTextureCopyTarget");
        SerializedProperty m_sTextureCopyTag = property.FindPropertyRelative("m_sTextureCopyTag");

        int indent = EditorGUI.indentLevel;
        EditorGUI.indentLevel = 0;

        m_eTextureModifyMode.isExpanded = EditorGUI.Foldout(new Rect(position.x, position.y, position.width, EditorGUIUtility.singleLineHeight),
                                                    m_eTextureModifyMode.isExpanded, new GUIContent("Texture Properties"), true);

        if(m_eTextureModifyMode.isExpanded)
        {
            EditorGUI.indentLevel++;

            EditorGUI.PropertyField(new Rect(position.x, position.y + EditorGUIUtility.singleLineHeight, position.width, EditorGUIUtility.singleLineHeight),m_eTextureModifyMode);

            if(m_eTextureModifyMode.enumValueIndex == (int)LPK_ModifySpriteOnEvent.LPK_NonNumericModifyMode.SET)
                EditorGUI.PropertyField(new Rect(position.x, position.y + EditorGUIUtility.singleLineHeight * 2, position.width, EditorGUIUtility.singleLineHeight),m_TextureValue);

            if(m_eTextureModifyMode.enumValueIndex == (int)LPK_ModifySpriteOnEvent.LPK_NonNumericModifyMode.COPY)
            {
                EditorGUI.PropertyField(new Rect(position.x, position.y + EditorGUIUtility.singleLineHeight * 2, position.width, EditorGUIUtility.singleLineHeight),m_pTextureCopyTarget);
                EditorGUI.PropertyField(new Rect(position.x, position.y + EditorGUIUtility.singleLineHeight * 3, position.width, EditorGUIUtility.singleLineHeight),m_sTextureCopyTag);
            }
        }

        EditorGUI.indentLevel = indent;

        property.serializedObject.ApplyModifiedProperties();
    }

    /**
    * FUNCTION NAME: GetPropertyHeight
    * DESCRIPTION  : Set height for this property in the inspector.
    * INPUTS       : property - Property to draw.
    *                label    - Display info.
    * OUTPUTS      : None
    **/
    public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
    {
        SerializedProperty m_eTextureModifyMode = property.FindPropertyRelative("m_eTextureModifyMode");

        if(m_eTextureModifyMode.enumValueIndex == (int)LPK_ModifySpriteOnEvent.LPK_NonNumericModifyMode.SET)
            return m_eTextureModifyMode.isExpanded ? EditorGUIUtility.singleLineHeight * 3 : EditorGUIUtility.singleLineHeight;
        else if (m_eTextureModifyMode.enumValueIndex == (int)LPK_ModifySpriteOnEvent.LPK_NonNumericModifyMode.COPY)
            return m_eTextureModifyMode.isExpanded ? EditorGUIUtility.singleLineHeight * 4 : EditorGUIUtility.singleLineHeight;
        else
            return m_eTextureModifyMode.isExpanded ? EditorGUIUtility.singleLineHeight * 2 : EditorGUIUtility.singleLineHeight;
    }
}

[CustomPropertyDrawer(typeof(LPK_ModifySpriteOnEvent.MaterialProperties))]
public class LPK_ModifySpriteOnEvent_MaterialPropertiesDrawer : PropertyDrawer
{
    /**
    * FUNCTION NAME: OnGUI
    * DESCRIPTION  : Override GUI for inspector.
    * INPUTS       : position - Position of the property drawer.
    *                property - Property to draw.
    *                label    - Display info.
    * OUTPUTS      : None
    **/
    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        SerializedProperty m_eMaterialModifyMode = property.FindPropertyRelative("m_eMaterialModifyMode");
        SerializedProperty m_MaterialValue = property.FindPropertyRelative("m_MaterialValue");
        SerializedProperty m_pMaterialCopyTarget = property.FindPropertyRelative("m_pMaterialCopyTarget");
        SerializedProperty m_sMaterialCopyTag = property.FindPropertyRelative("m_sMaterialCopyTag");

        int indent = EditorGUI.indentLevel;
        EditorGUI.indentLevel = 0;

        m_eMaterialModifyMode.isExpanded = EditorGUI.Foldout(new Rect(position.x, position.y, position.width, EditorGUIUtility.singleLineHeight),
                                                    m_eMaterialModifyMode.isExpanded, new GUIContent("Material Properties"), true);

        if(m_eMaterialModifyMode.isExpanded)
        {
            EditorGUI.indentLevel++;

            EditorGUI.PropertyField(new Rect(position.x, position.y + EditorGUIUtility.singleLineHeight, position.width, EditorGUIUtility.singleLineHeight),m_eMaterialModifyMode);

            if(m_eMaterialModifyMode.enumValueIndex == (int)LPK_ModifySpriteOnEvent.LPK_NonNumericModifyMode.SET)
                EditorGUI.PropertyField(new Rect(position.x, position.y + EditorGUIUtility.singleLineHeight * 2, position.width, EditorGUIUtility.singleLineHeight),m_MaterialValue);

            if(m_eMaterialModifyMode.enumValueIndex == (int)LPK_ModifySpriteOnEvent.LPK_NonNumericModifyMode.COPY)
            {
                EditorGUI.PropertyField(new Rect(position.x, position.y + EditorGUIUtility.singleLineHeight * 2, position.width, EditorGUIUtility.singleLineHeight),m_pMaterialCopyTarget);
                EditorGUI.PropertyField(new Rect(position.x, position.y + EditorGUIUtility.singleLineHeight * 3, position.width, EditorGUIUtility.singleLineHeight),m_sMaterialCopyTag);
            }
        }

        EditorGUI.indentLevel = indent;

        property.serializedObject.ApplyModifiedProperties();
    }

    /**
    * FUNCTION NAME: GetPropertyHeight
    * DESCRIPTION  : Set height for this property in the inspector.
    * INPUTS       : property - Property to draw.
    *                label    - Display info.
    * OUTPUTS      : None
    **/
    public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
    {
        SerializedProperty m_eMaterialModifyMode = property.FindPropertyRelative("m_eMaterialModifyMode");

        if(m_eMaterialModifyMode.enumValueIndex == (int)LPK_ModifySpriteOnEvent.LPK_NonNumericModifyMode.SET)
            return m_eMaterialModifyMode.isExpanded ? EditorGUIUtility.singleLineHeight * 3 : EditorGUIUtility.singleLineHeight;
        else if (m_eMaterialModifyMode.enumValueIndex == (int)LPK_ModifySpriteOnEvent.LPK_NonNumericModifyMode.COPY)
            return m_eMaterialModifyMode.isExpanded ? EditorGUIUtility.singleLineHeight * 4 : EditorGUIUtility.singleLineHeight;
        else
            return m_eMaterialModifyMode.isExpanded ? EditorGUIUtility.singleLineHeight * 2 : EditorGUIUtility.singleLineHeight;
    }
}

#endif  //UNITY_EDITOR

}   //LPK
